package org.python.core.adapter;
import org.python.core.Py;
import org.python.core.PyArray;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyJavaClass;
import org.python.core.PyJavaInstance;
import org.python.core.PyLong;
import org.python.core.PyObject;
import org.python.core.PyProxy;
import org.python.core.PyString;
import org.python.core.PyType;
/**
* Implements the algorithm originally used in {@link Py#java2py} to adapt objects.
*
* Pre-class adapters are added to handle instances of PyObject, PyProxy and
* null values. Class adapters are added to handle builtin Java classes: String,
* Integer, Float, Double, Byte, Long, Short, Character, Class and Boolean. An
* adapter is added to the post-class adapters to handle wrapping arrays
* properly. Finally, if all of the added adapters can handle an object, it's
* wrapped in a PyJavaInstance.
*
*/
public class ClassicPyObjectAdapter extends ExtensiblePyObjectAdapter {
public ClassicPyObjectAdapter() {
addPreClass(new PyObjectAdapter() {
public PyObject adapt(Object o) {
return (PyObject) o;
}
public boolean canAdapt(Object o) {
return o instanceof PyObject;
}
});
addPreClass(new PyObjectAdapter() {
public PyObject adapt(Object o) {
return ((PyProxy) o)._getPyInstance();
}
public boolean canAdapt(Object o) {
return o instanceof PyProxy;
}
});
addPreClass(new PyObjectAdapter() {
public boolean canAdapt(Object o) {
return o == null;
}
public PyObject adapt(Object o) {
return Py.None;
}
});
add(new ClassAdapter(String.class) {
public PyObject adapt(Object o) {
return new PyString((String) o);
}
});
add(new ClassAdapter(Character.class) {
public PyObject adapt(Object o) {
return Py.makeCharacter((Character) o);
}
});
add(new ClassAdapter(Class.class) {
public PyObject adapt(Object o) {
Class cls = (Class) o;
if (PyObject.class.isAssignableFrom(cls)) {
return PyType.fromClass(cls);
}
return PyJavaClass.lookup(cls);
}
});
add(new NumberToPyFloat(Double.class));
add(new NumberToPyFloat(Float.class));
add(new NumberToPyInteger(Integer.class));
add(new NumberToPyInteger(Byte.class));
add(new NumberToPyInteger(Short.class));
add(new ClassAdapter(Long.class) {
public PyObject adapt(Object o) {
return new PyLong(((Number) o).longValue());
}
});
add(new ClassAdapter(Boolean.class) {
public PyObject adapt(Object o) {
return ((Boolean) o).booleanValue() ? Py.One : Py.Zero;
}
});
addPostClass(new PyObjectAdapter() {
public PyObject adapt(Object o) {
return new PyArray(o.getClass().getComponentType(), o);
}
public boolean canAdapt(Object o) {
return o.getClass().isArray();
}
});
}
/**
* Always returns true as we just return new PyJavaInstance(o) if the
* adapters added to the superclass can't handle o.
*/
public boolean canAdapt(Object o) {
return true;
}
public PyObject adapt(Object o) {
PyObject result = super.adapt(o);
if (result != null) {
return result;
}
return new PyJavaInstance(o);
}
private static class NumberToPyInteger extends ClassAdapter {
public NumberToPyInteger(Class c) {
super(c);
}
public PyObject adapt(Object o) {
return new PyInteger(((Number) o).intValue());
}
}
private static class NumberToPyFloat extends ClassAdapter {
public NumberToPyFloat(Class c) {
super(c);
}
public PyObject adapt(Object o) {
return new PyFloat(((Number) o).doubleValue());
}
}
}